package com.beauty.order.controller;

import com.beauty.order.client.PaymentClient;
import com.beauty.order.dto.OrderRequest;
import com.beauty.order.dto.OrderResponse;
import com.beauty.order.dto.PageResponse;
import com.beauty.order.entity.Order;
import com.beauty.order.result.Result;
import com.beauty.order.service.OrderIntegrationService;
import com.beauty.order.service.OrderService;
import com.beauty.order.service.UserIntegrationService;
import com.fasterxml.jackson.core.JsonProcessingException;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
/**
 * 订单API接口
 * 
 * 该控制器提供订单相关的所有RESTful接口，包括：
 * - 订单的创建、查询、更新和删除
 * - 按不同条件（ID、订单号、客户ID、状态等）查询订单
 * - 订单状态管理
 * - 订单物流信息管理
 * - 与支付服务和用户服务的集成
 * 
 * 基础路径: /api/order
 * 支持的HTTP方法: GET, POST, PUT, DELETE
 */
@RequestMapping("/api/order")
@RequiredArgsConstructor
@Slf4j
public class OrderController {

    private final OrderService orderService;
    private final PaymentClient paymentClient;
    private final OrderIntegrationService orderIntegrationService;
    private final UserIntegrationService userIntegrationService;
    /**
     * 通过订单号更新订单状态
     */
    @PutMapping("/by-number/{orderNumber}/status")
    public Result<Order> updateOrderStatusByOrderNumber(
            @PathVariable String orderNumber,
            @RequestParam String status) {
        log.info("【订单服务】通过订单号更新订单状态: orderNumber={}, status={}", orderNumber, status);
        return Result.success(orderService.updateOrderStatusByOrderNumber(orderNumber, status));
    }
    @PostMapping
    public Result<OrderResponse> createOrder(@Valid @RequestBody OrderRequest orderRequest) throws JsonProcessingException {
        return Result.success(orderService.createOrder(orderRequest));
    }

    @GetMapping("/{id}")
    public Result<OrderResponse> getOrderById(@PathVariable Long id) {
        return Result.success(orderService.getOrderById(id));
    }

    @GetMapping("/number/{orderNumber}")
    public Result<OrderResponse> getOrderByOrderNumber(@PathVariable String orderNumber) {
        return Result.success(orderService.getOrderByOrderNumber(orderNumber));
    }

    @GetMapping("/customer/{customerId}")
    public Result<List<OrderResponse>> getOrdersByCustomerId(@PathVariable String customerId) {
        return Result.success(orderService.getOrdersByCustomerId(customerId));
    }

    @GetMapping("/status/{status}")
    public Result<List<OrderResponse>> getOrdersByStatus(@PathVariable Order.OrderStatus status) {
        return Result.success(orderService.getOrdersByStatus(status));
    }

    @GetMapping("/date")
    public Result<List<OrderResponse>> getOrdersByDateRange(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime start,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime end) {
        return Result.success(orderService.getOrdersByDateRange(start, end));
    }

    @GetMapping
    public Result<List<OrderResponse>> getAllOrders() {
        return Result.success(orderService.getAllOrders());
    }

    @PutMapping("/{id}/status")
    public Result<OrderResponse> updateOrderStatus(
            @PathVariable Long id,
            @RequestParam Order.OrderStatus status) {
        return Result.success(orderService.updateOrderStatus(id, status));
    }

    @PutMapping("/{id}/tracking")
    public Result<OrderResponse> updateTrackingNumber(
            @PathVariable Long id,
            @RequestParam String trackingNumber) {
        return Result.success(orderService.updateTrackingNumber(id, trackingNumber));
    }
    // 删除订单
    @DeleteMapping("/{id}")
    public Result<Void> deleteOrder(@PathVariable Long id) {
        orderService.deleteOrder(id);
        return Result.success();
    }
// 获取订单详情
    @GetMapping("/{id}/full")
    public Result<Map<String, Object>> getFullOrderInfo(@PathVariable Long id) {
        OrderResponse order = orderService.getOrderById(id);

        Map<String, Object> result = new HashMap<>();
        result.put("order", order);

        // 调用支付服务获取支付信息
        try {
            Object paymentResponse = paymentClient.getPaymentsByOrderId(order.getOrderNumber());
            result.put("payments", paymentResponse);
        } catch (Exception e) {
            result.put("paymentError", "无法获取支付信息: " + e.getMessage());
        }

        return Result.success(result);
    }

    @GetMapping("/{id}/shipment")
    public Result<Map<String, Object>> getOrderShipment(@PathVariable Long id) {
        OrderResponse order = orderService.getOrderById(id);
        return Result.success(orderIntegrationService.getOrderShipments(order.getOrderNumber()));
    }

    @GetMapping("/{id}/detail")
    public Result<Map<String, Object>> getOrderDetail(@PathVariable Long id) {
        log.info("【订单服务】接收到获取订单详情请求，订单ID: {}", id);

        // 获取订单信息
        OrderResponse orderResponse = orderService.getOrderById(id);

        // 获取用户信息
        Map<String, Object> userInfo = userIntegrationService.getUserInfo(orderResponse.getCustomerId());

        // 合并订单和用户信息
        Map<String, Object> orderDetail = new HashMap<>();
        orderDetail.put("order", orderResponse);
        orderDetail.put("customer", userInfo);

        // 添加物流信息（如果有）
        if (orderResponse.getTrackingNumber() != null && !orderResponse.getTrackingNumber().isEmpty()) {
            Map<String, Object> shipments = orderIntegrationService.getOrderShipments(orderResponse.getOrderNumber());
            orderDetail.put("shipment", shipments);
        }

        log.info("【订单服务】订单详情查询成功，订单号: {}", orderResponse.getOrderNumber());
        return Result.success(orderDetail);
    }

    /**
     * 获取订单分页列表
     * 
     * @param page 页码，默认为0（第一页）
     * @param size 每页记录数，默认为10
     * @param sort 排序字段，默认为orderDate（订单日期）
     * @param direction 排序方向，默认为desc（降序）
     * @return 包含分页订单数据的Result对象
     */
    @GetMapping("/page")
    public Result<PageResponse<OrderResponse>> getOrdersPage(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "orderDate") String sort,
            @RequestParam(defaultValue = "desc") String direction) {
        log.info("【订单服务】接收到获取订单分页请求: page={}, size={}, sort={}, direction={}", page, size, sort, direction);

        // 根据direction参数确定排序方向（升序或降序）
        Sort.Direction sortDirection = "asc".equalsIgnoreCase(direction) ? Sort.Direction.ASC : Sort.Direction.DESC;
        // 创建分页请求对象，包含页码、每页大小和排序信息
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortDirection, sort));

        // 调用订单服务获取分页数据
        PageResponse<OrderResponse> response = orderService.getOrdersPage(pageable);
        return Result.success(response);
    }

    /**
     * 获取指定客户的订单分页列表
     * 
     * @param customerId 客户ID，用于筛选特定客户的订单
     * @param page 页码，默认为0（第一页）
     * @param size 每页记录数，默认为10
     * @param sort 排序字段，默认为orderDate（订单日期）
     * @param direction 排序方向，默认为desc（降序）
     * @return 包含客户订单分页数据的Result对象
     */
    @GetMapping("/customer/{customerId}/page")
    public Result<PageResponse<OrderResponse>> getOrdersByCustomerIdPage(
            @PathVariable String customerId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "orderDate") String sort,
            @RequestParam(defaultValue = "desc") String direction) {
        log.info("【订单服务】接收到获取客户订单分页请求: customerId={}, page={}, size={}", customerId, page, size);

        // 根据direction参数确定排序方向（升序或降序）
        Sort.Direction sortDirection = "asc".equalsIgnoreCase(direction) ? Sort.Direction.ASC : Sort.Direction.DESC;
        // 创建分页请求对象，包含页码、每页大小和排序信息
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortDirection, sort));

        // 调用订单服务获取指定客户的分页订单数据
        PageResponse<OrderResponse> response = orderService.getOrdersByCustomerIdPage(customerId, pageable);
        return Result.success(response);
    }

    /**
     * 根据订单状态获取分页订单列表
     * 
     * @param status 订单状态，用于筛选特定状态的订单
     * @param page 页码，默认为0（第一页）
     * @param size 每页记录数，默认为10
     * @param sort 排序字段，默认为orderDate（订单日期）
     * @param direction 排序方向，默认为desc（降序）
     * @return 包含特定状态订单分页数据的Result对象
     */
    @GetMapping("/status/{status}/page")
    public Result<PageResponse<OrderResponse>> getOrdersByStatusPage(
            @PathVariable Order.OrderStatus status,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "orderDate") String sort,
            @RequestParam(defaultValue = "desc") String direction) {
        log.info("【订单服务】接收到获取指定状态订单分页请求: status={}, page={}, size={}", status, page, size);

        // 根据direction参数确定排序方向（升序或降序）
        Sort.Direction sortDirection = "asc".equalsIgnoreCase(direction) ? Sort.Direction.ASC : Sort.Direction.DESC;
        // 创建分页请求对象，包含页码、每页大小和排序信息
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortDirection, sort));

        // 调用订单服务获取指定状态的分页订单数据
        PageResponse<OrderResponse> response = orderService.getOrdersByStatusPage(status, pageable);
        return Result.success(response);
    }

    /**
     * 根据日期范围获取分页订单列表
     * 
     * @param start 开始日期时间，用于设置查询的时间下限
     * @param end 结束日期时间，用于设置查询的时间上限
     * @param page 页码，默认为0（第一页）
     * @param size 每页记录数，默认为10
     * @param sort 排序字段，默认为orderDate（订单日期）
     * @param direction 排序方向，默认为desc（降序）
     * @return 包含特定日期范围内订单分页数据的Result对象
     */
    @GetMapping("/date/page")
    public Result<PageResponse<OrderResponse>> getOrdersByDateRangePage(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime start,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime end,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "orderDate") String sort,
            @RequestParam(defaultValue = "desc") String direction) {
        log.info("【订单服务】接收到获取日期范围订单分页请求: start={}, end={}, page={}, size={}", start, end, page, size);

        // 根据direction参数确定排序方向（升序或降序）
        Sort.Direction sortDirection = "asc".equalsIgnoreCase(direction) ? Sort.Direction.ASC : Sort.Direction.DESC;
        // 创建分页请求对象，包含页码、每页大小和排序信息
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortDirection, sort));

        // 调用订单服务获取指定日期范围内的分页订单数据
        PageResponse<OrderResponse> response = orderService.getOrdersByDateRangePage(start, end, pageable);
        return Result.success(response);
    }

    /**
     * 根据用户提供的关键字、分页和排序信息搜索订单
     * 此方法使用Spring MVC的@GetMapping注解来处理HTTP GET请求，用于搜索订单
     * 它接受关键字参数用于模糊搜索，并提供分页和排序功能，默认按降序排序
     *
     * @param keyword 搜索关键字，用于模糊匹配订单信息
     * @param page 页码，从0开始，默认为0
     * @param size 每页大小，默认为10
     * @param sort 排序字段，默认为"orderDate"
     * @param direction 排序方向，"asc"表示升序，"desc"表示降序，默认为"desc"
     * @return 返回一个Result对象，包含分页的订单信息
     */
    @GetMapping("/search")
    public Result<PageResponse<OrderResponse>> searchOrders(
            @RequestParam String keyword,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "orderDate") String sort,
            @RequestParam(defaultValue = "desc") String direction) {
        // 记录日志，跟踪模糊查询请求的关键信息
        log.info("【订单服务】接收到模糊查询请求: keyword={}, page={}, size={}", keyword, page, size);

        // 根据请求的排序方向构建Sort.Direction对象
        Sort.Direction sortDirection = "asc".equalsIgnoreCase(direction) ? Sort.Direction.ASC : Sort.Direction.DESC;
        // 构建Pageable对象，用于分页和排序
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortDirection, sort));

        // 调用orderService的searchOrders方法执行搜索，并将结果封装到Result对象中返回
        PageResponse<OrderResponse> response = orderService.searchOrders(keyword, pageable);
        return Result.success(response);
    }

    /**
     * 执行订单的高级搜索操作
     *
     * 该方法允许通过多个可选参数进行订单搜索，包括订单号、客户ID、物流单号、备注、送货地址，
     * 并支持分页和排序功能参数详细说明：
     * - orderNumber: 订单号，可选参数，用于指定特定的订单号
     * - customerId: 客户ID，可选参数，用于指定特定的客户ID
     * - trackingNumber: 物流单号，可选参数，用于指定特定的物流单号
     * - notes: 备注，可选参数，用于指定订单中的特定备注信息
     * - shippingAddress: 送货地址，可选参数，用于指定特定的送货地址
     * - page: 页码，必选参数，默认值为0，用于指定搜索结果的页码
     * - size: 每页数量，必选参数，默认值为10，用于指定每页显示的搜索结果数量
     * - sort: 排序字段，必选参数，默认值为"orderDate"，用于指定搜索结果按哪个字段排序
     * - direction: 排序方向，必选参数，默认值为"desc"，可选值为"asc"或"desc"，用于指定搜索结果的排序方向
     *
     * 方法首先记录日志信息，然后根据传入的排序方向和排序字段构建排序对象，并创建分页请求对象
     * 最后，调用orderService的advancedSearch方法执行高级搜索，并返回搜索结果
     *
     * @param orderNumber 订单号，可选
     * @param customerId 客户ID，可选
     * @param trackingNumber 物流单号，可选
     * @param notes 备注，可选
     * @param shippingAddress 送货地址，可选
     * @param page 页码，必选，默认值为0
     * @param size 每页数量，必选，默认值为10
     * @param sort 排序字段，必选，默认值为"orderDate"
     * @param direction 排序方向，必选，默认值为"desc"
     * @return 包含订单搜索结果的分页响应
     */
    @GetMapping("/advanced-search")
    public Result<PageResponse<OrderResponse>> advancedSearch(
            @RequestParam(required = false) String orderNumber,
            @RequestParam(required = false) String customerId,
            @RequestParam(required = false) String trackingNumber,
            @RequestParam(required = false) String notes,
            @RequestParam(required = false) String shippingAddress,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "orderDate") String sort,
            @RequestParam(defaultValue = "desc") String direction) {
        // 记录高级搜索请求的日志信息
        log.info("【订单服务】接收到高级搜索请求，参数: 订单号={}, 客户ID={}, 物流单号={}, 页码={}, 每页数量={}",
                orderNumber, customerId, trackingNumber, page, size);

        // 根据传入的排序方向构建Sort.Direction对象
        Sort.Direction sortDirection = "asc".equalsIgnoreCase(direction) ? Sort.Direction.ASC : Sort.Direction.DESC;
        // 创建分页请求对象，包含页码、每页数量、排序方向和排序字段
        Pageable pageable = PageRequest.of(page, size, Sort.by(sortDirection, sort));

        // 调用orderService的advancedSearch方法执行高级搜索，并返回搜索结果
        PageResponse<OrderResponse> response = orderService.advancedSearch(
                orderNumber, customerId, trackingNumber, notes, shippingAddress, pageable);
        // 返回包含搜索结果的成功响应
        return Result.success(response);
    }

    /**
     * 获取可用物流承运商
     */
    @GetMapping("/available-carriers")
    public Result<?> getAvailableCarriers() {
        log.info("【订单服务】接收到获取可用物流承运商请求");
        List<Map<String, Object>> carriers = orderIntegrationService.getAvailableCarriers();
        return Result.success(carriers);
    }

    /**
     * 为订单创建物流单
     */
    @PostMapping("/{id}/shipment")
    public Result<?> createOrderShipment(
            @PathVariable Long id,
            @RequestParam String carrierName) {
        log.info("【订单服务】接收到为订单创建物流单请求: orderId={}, carrier={}", id, carrierName);
        Order order = orderService.getOrderByIdEntity(id);

        if (order == null) {
            return Result.failed("订单不存在");
        }

        // 检查订单状态
        if (order.getStatus() != Order.OrderStatus.PAID && order.getStatus() != Order.OrderStatus.PROCESSING) {
            return Result.failed("订单状态不允许创建物流单，当前状态: " + order.getStatus());
        }

        boolean success = orderIntegrationService.createShipment(order, carrierName);
        if (success) {
            // 创建成功后更新订单状态为SHIPPED
            OrderResponse response = orderService.updateOrderStatus(id, Order.OrderStatus.SHIPPED);
            return Result.success(response);
        } else {
            return Result.failed("创建物流单失败");
        }
    }
}
